﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Finance.Web.Models.Accounting
{
    public class DepositAmountAccounting : DepositAccounting
    {
        public double Calculate(DepostAccounting dep, out double[] byMonth)
        {
            using (FinanceContext context = new FinanceContext())
            {
                Deposit deposit = context.Deposites.FirstOrDefault(i => i.Code == dep.Deposit.Code);
                double percent = GetPercent(context, deposit, dep.Amount ?? 0);

                return Calculate(context, deposit, percent, deposit.PeriodPayment, dep.Amount, dep.AddAmount, out byMonth);
            }
        }

        private double Calculate(FinanceContext context, Deposit deposit, double percent, int? periodPayment, double? depamount, double ? depaddamoijnt, out double[] byMonth)
        {
            byMonth = new double[0];

            int period = periodPayment ?? 12;
            int spanPeriod = GetSpan(deposit.PaymentFrequesny);
            int freq = deposit.PaymentFrequesny ?? 12;

            var percentInPeriod = percent / freq;

            bool capit = deposit.Capitalization ?? false;
            double amount = depamount ?? 0;
            double initamount = amount;
            double addamount = depaddamoijnt ?? 0;

            double end = period * 30;

            for (int i = 1; i <= end; i++)
            {
                if (i % spanPeriod == 0)
                {
                    amount += percentInPeriod * initamount;
                    if (capit)
                        initamount = amount;
                }
                if (i % 30 == 0)
                {
                    byMonth = byMonth.Concat(new double[] { initamount }).ToArray();
                    if (i != end)
                    {
                        initamount += addamount;
                        amount += addamount;
                    }
                }
            }

            return amount;
        }



        public double CalculateAmount(DepostAccounting model)
        {
            double result = model.Amount.Value;

            using(FinanceContext context = new FinanceContext())
            {
                Deposit deposit = context.Deposites.FirstOrDefault(i => i.Code == model.Deposit.Code);
                double percent = GetPercent(context, deposit, 0);
                int freq = deposit.PaymentFrequesny ?? 12;
                int period = deposit.PeriodPayment ?? 12;

                return result / (Math.Pow(1 + percent / freq, freq * ( period / 12.0)));
            }

        }

        public double CalculateDeposit(UserDeposit model, DateTime now)
        {
            using (FinanceContext context = new FinanceContext())
            {
                Deposit deposit = context.Deposites.FirstOrDefault(i => i.Code == model.DepCode);
                int period = deposit.PeriodPayment ?? 12;

                DateTime opening = model.OpeningDate ?? now;

                double percent;

                double result =  model.Amount ?? 0;

                double [] byM;
                while (now.Subtract(opening).Days / 30 != 0 )
                {
                    if (opening.AddMonths(period) > now)
                    {
                        period = (int)now.Subtract(opening).Days / 30;
                        percent = GetPercent(context, deposit, period);
                    }
                    else
                    {
                        percent = GetPercent(context, deposit, result);
                    }
                    result = Calculate(context, deposit, percent, period, result, 0, out byM);
                    opening = opening.AddMonths(period);
                }

                return result;
            }
        }
    }
}